#![allow(dead_code)]
type NextNode<T> = Option<Box<Node<T>>>;

struct Node<T> {
    elem: T,
    next: NextNode<T>,
}

impl<T> Node<T> {
    fn new(elem: T) -> Self {
        Self { elem, next: None }
    }

    fn set_next(&mut self, node: Option<Self>) {
        self.next = None;
        if let Some(node) = node {
            self.next = Some(Box::new(node));
        }
    }

    fn get_next(&mut self) -> Option<&mut Self> {
        if let Some(ref mut node) = self.next {
            return Some(node);
        }
        None
    }

    fn get(&mut self, idx: usize) -> Option<&mut Self> {
        if idx == 0 {
            return Some(self);
        }
        if let Some(next) = self.get_next() {
            next.get(idx - 1)
        } else {
            None
        }
    }

    fn get_last_mut(&mut self) -> &mut Self {
        if let Some(ref mut next) = self.next {
            next.get_last_mut()
        } else {
            self
        }
    }

    fn get_last(&self) -> &Self {
        if let Some(ref next) = self.next {
            next.get_last()
        } else {
            self
        }
    }

    fn get_value(&self) -> &T {
        &self.elem
    }

    fn push(&mut self, elem: T) {
        self.get_last_mut().set_next(Some(Node::new(elem)));
    }
}

pub struct List<T> {
    len: usize,
    next: NextNode<T>,
}

impl<T> List<T> {
    pub fn new() -> Self {
        Self { len: 0, next: None }
    }

    fn get_next_mut(&mut self) -> Option<&mut Node<T>> {
        if let Some(ref mut node) = self.next {
            node.get_next()
        } else {
            None
        }
    }

    fn get_mut(&mut self, idx: usize) -> Option<&mut Node<T>> {
        if idx >= self.len || idx == 0 {
            return None;
        }

        let node = self.get_next_mut().unwrap();
        if idx == 1 {
            Some(node)
        } else {
            node.get(idx - 1)
        }
    }

    fn get_last_mut(&mut self) -> Option<&mut Node<T>> {
        if let Some(ref mut node) = self.next {
            Some(node.get_last_mut())
        } else {
            None
        }
    }

    fn get_last(&self) -> Option<&Node<T>> {
        if let Some(ref node) = self.next {
            Some(node.get_last())
        } else {
            None
        }
    }

    fn get_last_value(&self) -> Option<&T> {
        if self.len == 0 {
            None
        } else {
            Some(self.get_last().unwrap().get_value())
        }
    }

    fn push(&mut self, elem: T) {
        if self.len == 0 {
            self.next = Some(Box::new(Node::new(elem)));
        } else {
            if let Some(node) = self.get_last_mut() {
                node.push(elem);
            }
        }
        self.len += 1;
    }

    fn pop(&mut self) {
        if self.len == 0 {
            return;
        }
        self.len -= 1;
        let idx = self.len;
        self.get_mut(idx - 1).unwrap().set_next(None);
    }

    fn len(&self) -> usize {
        self.len
    }
}
